package com.cxhome.cxinfox.export;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.poi.hssf.util.Region;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import com.google.common.base.Preconditions;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Record;

public class PoiKitNew_Utils {

	private static final int HEADER_ROW = 1;
	public static final int MAX_ROWS = 65530;

	private String sheetName = "new sheet";
	private int cellWidth = 8000;
	private int headerRow;
	private String[] headers = new String[] {};
	private String[] columns;
	private int flushNum = 100;
	private SXSSFWorkbook wb = new SXSSFWorkbook(flushNum);

	public void export(List<?> data, String sheetName_) {
		Preconditions.checkNotNull(headers, "headers can not be null");
		Preconditions.checkNotNull(columns, "columns can not be null");
		Preconditions.checkArgument(cellWidth >= 0, "cellWidth < 0");

		Row row = null;
		Cell cell = null;
		Sheet sheet = wb.createSheet(sheetName_);
		if (headers.length > 0) {
			row = sheet.createRow(0);
			if (headerRow <= 0) {
				headerRow = HEADER_ROW;
			}
			headerRow = Math.min(headerRow, MAX_ROWS);
			for (int h = 0, lenH = headers.length; h < lenH; h++) {
				@SuppressWarnings("deprecation")
				Region region = new Region(0, (short) h, (short) headerRow - 1, (short) h);// 合并从第rowFrom行columnFrom列
				// sheet.addMergedRegion(region);// 到rowTo行columnTo的区域
				// 得到所有区域
				sheet.getNumMergedRegions();
				if (cellWidth > 0) {
					sheet.setColumnWidth(h, cellWidth);
				}
				cell = row.createCell(h);
				cell.setCellValue(headers[h]);
			}
		}

		if (data.size() == 0) {
			return;
		}

		Object obj = null;
		for (int j = 0; j < data.size(); j++) {
			obj = data.get(j);
			row = sheet.createRow(j + headerRow);
			if (obj == null) {
				continue;
			}

			if (obj instanceof Map) {
				processAsMap(columns, row, obj);
			} else if (obj instanceof Model) {
				processAsModel(columns, row, obj);
			} else if (obj instanceof Record) {
				processAsRecord(columns, row, obj);
			}

			if (j % flushNum == 0) {
				try {
					((SXSSFSheet) sheet).flushRows();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

	@SuppressWarnings("unchecked")
	private static void processAsMap(String[] columns, Row row, Object obj) {
		Cell cell;
		Map<String, Object> map = (Map<String, Object>) obj;
		if (columns.length == 0) {// 未设置显示列，默认全部
			Set<String> keys = map.keySet();
			int columnIndex = 0;
			for (String key : keys) {
				cell = row.createCell(columnIndex);
				cell.setCellValue(map.get(key) + "");
				columnIndex++;
			}
		} else {
			for (int j = 0, lenJ = columns.length; j < lenJ; j++) {
				cell = row.createCell(j);
				cell.setCellValue(map.get(columns[j]) + "");
			}
		}
	}

	private static void processAsModel(String[] columns, Row row, Object obj) {
		Cell cell;
		Model<?> model = (Model<?>) obj;
		Set<Entry<String, Object>> entries = model.getAttrsEntrySet();
		if (columns.length == 0) {// 未设置显示列，默认全部
			int columnIndex = 0;
			for (Entry<String, Object> entry : entries) {
				cell = row.createCell(columnIndex);
				cell.setCellValue(entry.getValue() + "");
				columnIndex++;
			}
		} else {
			for (int j = 0, lenJ = columns.length; j < lenJ; j++) {
				cell = row.createCell(j);
				cell.setCellValue(model.get(columns[j]) + "");
			}
		}
	}

	private static void processAsRecord(String[] columns, Row row, Object obj) {
		Cell cell;
		Record record = (Record) obj;
		Map<String, Object> map = record.getColumns();
		if (columns.length == 0) {// 未设置显示列，默认全部
			record.getColumns();
			Set<String> keys = map.keySet();
			int columnIndex = 0;
			for (String key : keys) {
				cell = row.createCell(columnIndex);
				cell.setCellValue(record.get(key) + "");
				columnIndex++;
			}
		} else {
			for (int j = 0, lenJ = columns.length; j < lenJ; j++) {
				cell = row.createCell(j);
				cell.setCellValue(map.get(columns[j]) + "");
			}
		}
	}

	public PoiKitNew_Utils sheetName(String sheetName) {
		this.sheetName = sheetName;
		return this;
	}

	public PoiKitNew_Utils cellWidth(int cellWidth) {
		this.cellWidth = cellWidth;
		return this;
	}

	public PoiKitNew_Utils headerRow(int headerRow) {
		this.headerRow = headerRow;
		return this;
	}

	public PoiKitNew_Utils headers(String[] headers) {
		this.headers = headers;
		return this;
	}

	public PoiKitNew_Utils columns(String[] columns) {
		this.columns = columns;
		return this;
	}

	public SXSSFWorkbook getWb() {
		return wb;
	}

}
